﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Excel = Microsoft.Office.Interop.Excel; 

namespace DesicionTreeViewer
{
    public struct CLoadedData
    {
        //кол-во элементов в выборке
        public int TrainingDataSize;
        //<название признака, список значений признаков>
        public List<KeyValuePair<String, List<double>>> Data;

        //true, если данные синхронизированы
        public bool AreSynchronized( CLoadedData otherData )
        {
            //кол-во столбцов должно совпадать
            if (Data.Count != otherData.Data.Count)
            {
                return false;
            }

            //проверяем на равенство названий признаков
            List<KeyValuePair<String, List<double>>>.Enumerator thisEnumerator = Data.GetEnumerator();
            List<KeyValuePair<String, List<double>>>.Enumerator otherEnumerator = otherData.Data.GetEnumerator();
            while ( thisEnumerator.MoveNext() && otherEnumerator.MoveNext())
            {
                if (thisEnumerator.Current.Key != otherEnumerator.Current.Key)
                {
                    return false;
                }
            }

            return true;
        }

    }
    class DataLoader
    {
        private CLoadedData firstTypeData;
        private CLoadedData secondTypeData;
        private CLoadedData observableData;

        public CLoadedData FirstTypeData
        {
            get { return firstTypeData; }

        }

        public CLoadedData ObservableData
        {
            get { return observableData; }

        }

        public CLoadedData SecondTypeData
        {
            get { return secondTypeData; }

        }

        public bool LoadExcelFile(String path)
        {
            try
            {
                Excel.Application excelApplication = new Excel.ApplicationClass();
                Excel.Workbook excelWorkBook = excelApplication.Workbooks.Open(path, 0, true, 5, "", "", true,
                    Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);

                //загружаем объекты первого типа
                Excel.Worksheet xlWorkSecondTypeObjectSheet = (Excel.Worksheet)excelWorkBook.Worksheets.get_Item(1);
                firstTypeData = loadDataFromSheet(xlWorkSecondTypeObjectSheet);
                releaseObject(xlWorkSecondTypeObjectSheet);

                //загружаем объекты второго типа
                Excel.Worksheet xlWorkFirstTypeObjectSheet = (Excel.Worksheet)excelWorkBook.Worksheets.get_Item(2);
                secondTypeData = loadDataFromSheet(xlWorkFirstTypeObjectSheet);
                releaseObject(xlWorkFirstTypeObjectSheet);

                if (excelWorkBook.Worksheets.Count > 2)
                {
                    //загружаем объекты наблюдения
                    Excel.Worksheet xlWorkSheetObservableData = (Excel.Worksheet)excelWorkBook.Worksheets.get_Item(3);
                    observableData = loadDataFromSheet(xlWorkSheetObservableData);
                    releaseObject(xlWorkSheetObservableData);
                }
                else
                {
                    observableData = new CLoadedData();
                    observableData.TrainingDataSize = 0;
                }

                releaseObject(excelWorkBook);
                releaseObject(excelApplication);
            }
            catch( Exception exception )
            {
                System.Windows.MessageBox.Show(exception.Message);
                return false;
            }
            
            return true;
        }

        //считывает данные из одной страницы Excel'а
        private CLoadedData loadDataFromSheet(Excel.Worksheet workSheet)
        {
            CLoadedData loadedData = new CLoadedData();
            loadedData.Data = new List<KeyValuePair<String, List<double>>>();

            Excel.Range range = workSheet.UsedRange;

            //считаем, что кол-во элементов в выборке - кол-во строк - 1( шапка)
            loadedData.TrainingDataSize = range.Rows.Count - 1;

            for (int columnCount = 2; columnCount <= range.Columns.Count; columnCount++ )
            {
                KeyValuePair<String, List<double>> newAttribute =
                    new KeyValuePair<string, List<double>>(
                        //название признака
                        (string)(range.Cells[1, columnCount] as Excel.Range).Value2,
                        //список значений признаков
                        new List<double>() );

                for (int rowCount = 2; rowCount <= range.Rows.Count; rowCount++ )
                {
                    if ((range.Cells[rowCount, columnCount] as Excel.Range).Value2 is double)
                    {
                        newAttribute.Value.Add((double)(range.Cells[rowCount, columnCount] as Excel.Range).Value2);
                    }
                    else
                    {
                        throw new Exception("bad format");
                    }
                }

                loadedData.Data.Add(newAttribute);
            }

            return loadedData;
        }

        private void releaseObject(object obj)
        {
            try
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
                obj = null;
            }
            catch (Exception ex)
            {
                obj = null;
                throw new Exception("Unable to release the Object " + ex.ToString());
            }
            finally
            {
                GC.Collect();
            }
        } 
    }
}
